package com.wsoft.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wsoft.cms.entity.CmsAnnouncementCommentEntity;
import com.wsoft.cms.entity.CmsAnnouncementEntity;
import com.wsoft.cms.query.announcement.AnnouncementListQuery;
import com.wsoft.core.utils.SqlAuthDisableHolder;
import com.wsoft.core.vo.MemberVO;
import com.wsoft.enums.PublishStatusEnum;
import com.wsoft.cms.enums.SummaryTypeEnum;
import com.wsoft.cms.manager.CmsAnnouncementCommentManager;
import com.wsoft.cms.manager.CmsAnnouncementManager;
import com.wsoft.cms.manager.CmsAnnouncementSummaryManager;
import com.wsoft.cms.mapper.CmsAnnouncementCommentMapper;
import com.wsoft.cms.query.comment.CommentInsertQuery;
import com.wsoft.cms.query.comment.CommentListInfoQuery;
import com.wsoft.cms.query.comment.CommentListQuery;
import com.wsoft.cms.query.comment.CommentMainListQuery;
import com.wsoft.cms.service.ICmsAnnouncementCommentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wsoft.cms.vo.comment.CommentVO;
import com.wsoft.cms.vo.comment.MainCommentVO;
import com.wsoft.core.exception.Asserts;
import com.wsoft.core.service.CommonMemberService;
import com.wsoft.core.utils.LoginUserUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 公告评价表 服务实现类
 * </p>
 *
 * @author juiet
 * @since 2024年11月27日 10:37:58
 */
@Service
public class CmsAnnouncementCommentServiceImpl extends ServiceImpl<CmsAnnouncementCommentMapper, CmsAnnouncementCommentEntity> implements ICmsAnnouncementCommentService {

    @Resource
    private CmsAnnouncementCommentManager commentManager;
    @Resource
    private CommonMemberService memberService;
    @Resource
    private CmsAnnouncementSummaryManager summaryManager;
    @Resource
    private CmsAnnouncementManager announcementManager;

    /**
     * 新增评论
     * @param query
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized boolean insertComment(CommentInsertQuery query) {
        CmsAnnouncementCommentEntity entity = buildComment(query);
        //保存评论表
        commentManager.save(entity);

        //评论的评论
        if(null != entity.getCommentId()){
            List<String> parentIdList = Arrays.asList(entity.getPath().split(StrUtil.COMMA));
            //递归 父节点
            List<CmsAnnouncementCommentEntity> parentComment = getAllParentComment(entity, commentManager.getById(parentIdList));
            //新增评论 .评论数 + 1
            handlerCommentCount(parentComment,1);
        }

        //文章评论数 + 1
        summaryManager.addCount(entity.getAnnoId(), SummaryTypeEnum.COMMENT.getType(), 1);

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized boolean deleteComment(Long commentId,boolean isUser) {
        CmsAnnouncementCommentEntity comment = commentManager.getById(commentId);
        if(isUser){
            Long id = LoginUserUtil.getUserInfo().getLoginUserVO().getId();
            if(!comment.getMemberId().equals(id)){
                //不能删除他人评论
                Asserts.fail("[cms.comment.del.error]");
            }
        }
        //删除评论
        commentManager.delById(commentId);

        //评论的评论
        if(null != comment.getCommentId()){
            List<String> parentIdList = Arrays.asList(comment.getPath().split(StrUtil.COMMA));
            //递归 父节点
            List<CmsAnnouncementCommentEntity> parentComment = getAllParentComment(comment, commentManager.getById(parentIdList));
            //删除评论 .评论数 - comment.getCommentCount()
            handlerCommentCount(parentComment,- (comment.getCommentCount().intValue() + 1));
        }

        //文章评论数 + 1
        summaryManager.addCount(comment.getAnnoId(), SummaryTypeEnum.COMMENT.getType(), -(comment.getCommentCount().intValue() + 1 ));

        return true;
    }

    @Override
    public PageInfo getChildCommentPage(CommentListQuery query) {
        SqlAuthDisableHolder.open();
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<CmsAnnouncementCommentEntity> list = commentManager.getChildPage(query.getCommentId(),null);
        PageInfo pageInfo = PageInfo.of(list);
        //组装评论者 姓名
        List<CommentVO> collect = buildCommentName(list, query.getCommentId());
        SqlAuthDisableHolder.close();
        pageInfo.setList(collect);
        return pageInfo;
    }


    /**
     * 获取主评论分页
     * @param query
     * @return
     */
    @Override
    public PageInfo<MainCommentVO> getMainCommentPage(CommentMainListQuery query) {
        AnnouncementListQuery listQuery = new AnnouncementListQuery();
        List<CmsAnnouncementEntity> annoList = announcementManager.listAnnoQuery(listQuery, true, query.getAnnoId());
        if(CollUtil.isEmpty(annoList)){
            //无权限查看
            Asserts.fail("[cms.view.error]");
        }

        SqlAuthDisableHolder.open();
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<CmsAnnouncementCommentEntity> list = commentManager.getMainPage(query.getAnnoId());
        PageInfo pageInfo = PageInfo.of(list);

        List<MainCommentVO> collect = list.stream().map(item -> Convert.convert(MainCommentVO.class, item)).collect(Collectors.toList());
        for (MainCommentVO mainCommentVO : collect) {
            MemberVO memberVO = memberService.getMemberInfo(mainCommentVO.getMemberId());
            mainCommentVO.setMemberName(memberVO.getName());
            mainCommentVO.setMemberPhoto(memberVO.getPhoto());
            List<CmsAnnouncementCommentEntity> childComment = commentManager.getChildPage(mainCommentVO.getId(),3);
            if(CollUtil.isNotEmpty(childComment)){
                //组装评论者 姓名
                mainCommentVO.setChildCommentVO(buildCommentName(childComment,mainCommentVO.getId()));
            }
        }
        SqlAuthDisableHolder.close();
        pageInfo.setList(collect);
        return pageInfo;
    }

    @Override
    public PageInfo<CmsAnnouncementCommentEntity> listCommon(CommentListInfoQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        SqlAuthDisableHolder.open();
        PageInfo<CmsAnnouncementCommentEntity> pageInfo = PageInfo.of(commentManager.listCommon(query));
        SqlAuthDisableHolder.close();
        return pageInfo;
    }


    // ################################## 私有方法  ##################################


    /**
     * 组装 commentEntity
     * @param query
     * @return
     */
    private CmsAnnouncementCommentEntity buildComment(CommentInsertQuery query){
        CmsAnnouncementEntity entity = announcementManager.getById(query.getAnnoId());
        if(entity == null || !PublishStatusEnum.PUBLISH.getType().equals(entity.getSendStatus()) ||entity.getIsComment() == 0){
            //当前不允许评论
            Asserts.fail("[cms.comment.error]");
        }

        CmsAnnouncementCommentEntity commentEntity = new CmsAnnouncementCommentEntity();
        commentEntity.setAnnoId(query.getAnnoId());
        commentEntity.setMemberId(LoginUserUtil.getUserInfo().getLoginUserVO().getId());
        commentEntity.setComment(query.getComment());
        commentEntity.setCommentTime(LocalDateTime.now());
        if(query.getCommentId() != null){
            commentEntity.setCommentId(query.getCommentId());
            CmsAnnouncementCommentEntity comment = commentManager.getById(query.getCommentId());
            commentEntity.setCommentMemberId(comment.getMemberId());
            String path = StrUtil.isBlank(comment.getPath()) ? String.valueOf(comment.getId()) : comment.getPath() + StrUtil.COMMA + comment.getId();
            commentEntity.setPath(path);
        }
        commentEntity.setCommentCount(0L);
        return commentEntity;

    }



    /**
     * 批量跟新 评论数量
     * @param list
     * @param count
     * @return
     */
    private boolean handlerCommentCount(List<CmsAnnouncementCommentEntity> list,int count){
        for (CmsAnnouncementCommentEntity commentEntity : list) {
            commentEntity.setCommentCount(commentEntity.getCommentCount() + count);
        }
        return commentManager.updateBatchById(list);
    }


    /**
     * 获取当前节点的 所有上级节点
     * @param node 当前节点
     * @param nodes 所有节点
     * @return
     */
    private static List<CmsAnnouncementCommentEntity> getAllParentComment(CmsAnnouncementCommentEntity node, List<CmsAnnouncementCommentEntity> nodes) {
        // 创建一个映射，用于快速查找节点
        Map<Long, CmsAnnouncementCommentEntity> nodeMap = new HashMap<>(16);
        for (CmsAnnouncementCommentEntity n : nodes) {
            nodeMap.put(n.getId(), n);
        }

        // 调用递归方法查找所有上级节点
        List<CmsAnnouncementCommentEntity> parents = new ArrayList<>();
        findParents(node, nodeMap, parents);

        return parents;
    }

    /**
     * 递归查找上级节点
     * @param node
     * @param nodeMap
     * @param parents
     */
    private static void findParents(CmsAnnouncementCommentEntity node, Map<Long, CmsAnnouncementCommentEntity> nodeMap, List<CmsAnnouncementCommentEntity> parents) {
        // 获取当前节点的父节点
        CmsAnnouncementCommentEntity parent = nodeMap.get(node.getCommentId());
        if (parent != null) {
            // 将父节点添加到列表中
            parents.add(parent);
            // 递归查找父节点的父节点
            findParents(parent, nodeMap, parents);
        }
    }


    /**
     * 获取当前节点的 所有下级评论
     * @param node 当前节点
     * @param nodes 所有节点
     * @return
     */
    public static List<CmsAnnouncementCommentEntity> getAllChildComment(CmsAnnouncementCommentEntity node, List<CmsAnnouncementCommentEntity> nodes) {
        // 创建一个映射，用于快速查找节点
        Map<Long, List<CmsAnnouncementCommentEntity>> nodeMap = new HashMap<>(16);
        for (CmsAnnouncementCommentEntity n : nodes) {
            nodeMap.computeIfAbsent(n.getCommentId(), k -> new ArrayList<>()).add(n);
        }

        // 调用递归方法查找所有下级节点
        List<CmsAnnouncementCommentEntity> children = new ArrayList<>();
        findChildren(node, nodeMap, children);

        return children;
    }

    /**
     * 递归查找下级节点
     * @param node
     * @param nodeMap
     * @param children
     */
    private static void findChildren(CmsAnnouncementCommentEntity node, Map<Long, List<CmsAnnouncementCommentEntity>> nodeMap, List<CmsAnnouncementCommentEntity> children) {
        // 获取当前节点的下级节点
        List<CmsAnnouncementCommentEntity> childNodes = nodeMap.get(node.getId());
        if (childNodes != null) {
            for (CmsAnnouncementCommentEntity child : childNodes) {
                // 将下级节点添加到列表中
                children.add(child);
                // 递归查找下级节点的下级节点
                findChildren(child, nodeMap, children);
            }
        }
    }


    /**
     * 组装评论姓名
     * @param list
     * @param commentId
     * @return
     */
    private List<CommentVO>  buildCommentName(List<CmsAnnouncementCommentEntity> list,Long commentId){
        if(CollUtil.isEmpty(list)){
            return new ArrayList<>();
        }
        List<CommentVO> collect = list.stream().map(item -> Convert.convert(CommentVO.class, item)).collect(Collectors.toList());
        for (CommentVO commentVO : collect) {
            //赋值评论人姓名
            MemberVO memberVO = memberService.getMemberInfo(commentVO.getMemberId());
            commentVO.setMemberName(memberVO.getName());
            commentVO.setMemberPhoto(memberVO.getPhoto());
            commentVO.setCommentMemberName("");
            if(!commentVO.getCommentId().equals(commentId)){
                //赋值 回复人姓名
                commentVO.setCommentMemberName(memberService.getMemberInfo(commentVO.getCommentMemberId()).getName());
            }
        }
        return collect;
    }

}
